

#include <base.h>

#include <stdio.h>
#include <string.h>
#include <assert.h>

#define TOTALCLASSES_LOG2B(x)		(x * 2)

#define TOTALCLASSES(name, x)		__MCAT(TOTALCLASSES, _LOG2B)(x)

#define AC		4
#define KBC		AC

/* 这种不行 */
int abccc[] = { TOTALCLASSES(LOG2B, 1)};
// int abcc[] = { LOG2_M(16384), LOG2_M(8), LOG2_M(KBC), LOG2_M(POW2_M(AC))};
// static inline gopt_t test_option_func(word_t arg){
// 	void *ret = (void *)(arg + 1);
// 	return GOPT_OK(ret);
// }

/* 这种方式可以使用带函数的constexpr */
// static const int dxdp = __builtin_clz(6);
// int abccf[] = {dxdp, 2};

/* 函数不可以 */
// static const int functestp(){
//	 return __builtin_clz(6);
// }
// static const int dxcc = functestp();
// int abccff[] = {dxcc, dxdp};

// void test_option(){
// 	assert(GOPT_UNWRAP(test_option_func(1)) == 2);
// }

void test_str(){
	const char *a = TO_STRING(test to string);
	const char *c = TO_STRING(__MCAT(test to string,_concat));
	const char *t = TO_STRING(MCAT(a,b,c,d,ef,g));
	assert(0 == strcmp(t, "abcdefg"));
	assert(0 == strcmp("test to string", a));
	assert(0 == strcmp("test to string_concat", c));
}

void test_argc(){
	int b = ARGC_SAFE(c,b,a,d);
	assert(b == 4);
	int a = ARGC(c,b,a,d);
	assert(a == 4);
	int t = ARGC(   255,254,253,252,251,250,						\
					249,248,247,246,245,244,243,242,241,240,		\
					239,238,237,236,235,234,233,232,231,230,		\
					229,228,227,226,225,224,223,222,221,220,		\
					219,218,217,216,215,214,213,212,211,210,		\
					209,208,207,206,205,204,203,202,201,200,		\
					199,198,197,196,195,194,193,192,191,190,		\
					189,188,187,186,185,184,183,182,181,180,		\
					179,178,177,176,175,174,173,172,171,170,		\
					169,168,167,166,165,164,163,162,161,160,		\
					159,158,157,156,155,154,153,152,151,150,		\
					149,148,147,146,145,144,143,142,141,140,		\
					139,138,137,136,135,134,133,132,131,130,		\
					129,128,127,126,125,124,123,122,121,120,		\
					119,118,117,116,115,114,113,112,111,110,		\
					109,108,107,106,105,104,103,102,101,100,		\
					99,98,97,96,95,94,93,92,91,90,				  \
					89,88,87,86,85,84,83,82,81,80,				  \
					79,78,77,76,75,74,73,72,71,70,				  \
					69,68,67,66,65,64,63,62,61,60,				  \
					59,58,57,56,55,54,53,52,51,50,				  \
					49,48,47,46,45,44,43,42,41,40,				  \
					39,38,37,36,35,34,33,32,31,30,				  \
					29,28,27,26,25,24,23,22,21,20,				  \
					19,18,17,16,15,14,13,12,11,10,				  \
					9,8,7,6,5,4,3,2,1);
	assert(t == 255);

	t = ARGC_SAFE(   255,254,253,252,251,250,						\
					249,248,247,246,245,244,243,242,241,240,		\
					239,238,237,236,235,234,233,232,231,230,		\
					229,228,227,226,225,224,223,222,221,220,		\
					219,218,217,216,215,214,213,212,211,210,		\
					209,208,207,206,205,204,203,202,201,200,		\
					199,198,197,196,195,194,193,192,191,190,		\
					189,188,187,186,185,184,183,182,181,180,		\
					179,178,177,176,175,174,173,172,171,170,		\
					169,168,167,166,165,164,163,162,161,160,		\
					159,158,157,156,155,154,153,152,151,150,		\
					149,148,147,146,145,144,143,142,141,140,		\
					139,138,137,136,135,134,133,132,131,130,		\
					129,128,127,126,125,124,123,122,121,120,		\
					119,118,117,116,115,114,113,112,111,110,		\
					109,108,107,106,105,104,103,102,101,100,		\
					99,98,97,96,95,94,93,92,91,90,				  \
					89,88,87,86,85,84,83,82,81,80,				  \
					79,78,77,76,75,74,73,72,71,70,				  \
					69,68,67,66,65,64,63,62,61,60,				  \
					59,58,57,56,55,54,53,52,51,50,				  \
					49,48,47,46,45,44,43,42,41,40,				  \
					39,38,37,36,35,34,33,32,31,30,				  \
					29,28,27,26,25,24,23,22,21,20,				  \
					19,18,17,16,15,14,13,12				  );
	assert(t == 244);
	/* 溢出场景 */
	int p = ARGC(   257,256,255,254,253,252,251,250,						\
					249,248,247,246,245,244,243,242,241,240,		\
					239,238,237,236,235,234,233,232,231,230,		\
					229,228,227,226,225,224,223,222,221,220,		\
					219,218,217,216,215,214,213,212,211,210,		\
					209,208,207,206,205,204,203,202,201,200,		\
					199,198,197,196,195,194,193,192,191,190,		\
					189,188,187,186,185,184,183,182,181,180,		\
					179,178,177,176,175,174,173,172,171,170,		\
					169,168,167,166,165,164,163,162,161,160,		\
					159,158,157,156,155,154,153,152,151,150,		\
					149,148,147,146,145,144,143,142,141,140,		\
					139,138,137,136,135,134,133,132,131,130,		\
					129,128,127,126,125,124,123,122,121,120,		\
					119,118,117,116,115,114,113,112,111,110,		\
					109,108,107,106,105,104,103,102,101,100,		\
					99,98,97,96,95,94,93,92,91,90,				  \
					89,88,87,86,85,84,83,82,81,80,				  \
					79,78,77,76,75,74,73,72,71,70,				  \
					69,68,67,66,65,64,63,62,61,60,				  \
					59,58,57,56,55,54,53,52,51,50,				  \
					49,48,47,46,45,44,43,42,41,40,				  \
					39,38,37,36,35,34,33,32,31,30,				  \
					29,28,27,26,25,24,23,22,21,20,				  \
					19,18,17,16,15,14,13,12,11,10,				  \
					9,8,7,6,5,4,3,2,1);
	assert(p == 2);
}




#define M(i, _)	i,

int __func(int x){
	return x + 1;
}
int __func1(int x1, int x2){
	return x1+x2+1;
}
// #define __FOLD_LE(x, y)	 MIF_ELSE(EQ8(x, y),)

int test_le8(){
	// int a = EXPAND(__REC_LE(1, 255));
	// int b = FOLDL(__FOLD_LE, 1, RANGE8(5));
	// int a = LE8(1, 4);
	// assert(LE8(1, 2) == 1);
	// assert(LE8(1, 3) == 1);
	// assert(LE8(1, 0) == 0);
	// assert(LE8(254, 0) == 0);
	// assert(LE8(254, 255) == 1);
	// assert(LE8(255, 255) == 1);
	// assert(LE8(127, 255) == 1);
	return 0;
}

// #define __FUNC_ARGLIST(x) arg##x
#define __RSWAP(x1, x2)	  (x2, __UNMLIST x1)
#define RSWAP(x, ...)		EVAL(__UNMLIST FOLDL(__RSWAP, (x), __VA_ARGS__))

void test_eval(){
	
	/* 出错 DEFER(NOTB)(0) */
	int c = EXPAND(DEFER(NOTB)(0));
	assert(c == 1);

	assert(1 == IS_PAREN(()));
	assert(0 == IS_PAREN());
	assert(0 == IS_PAREN(x));


	// __TEST_EVAL(NOTB(0));
	int k[] = {EVAL(REPEAT(8, M, ~))};
	assert(k[7] == 7);
	MAPS(__func, 0);
	MAPS(__func, 0, 1, 2);
	MAPLS(__func1, (0, 1), (1, 2), (3, 4));
	
	/* 怎么拼接出第三个元素 */


	MAPLS(__func1, GEN_PAIRLIST(0, 1, 2, 3, 4, 5));
	MAPLS(__func1, GEN_PAIRLIST(0, 1));
	// MAPC(__func, 0, 1, 2, 3, 4);
	__func1(RANGE8(2));
	// MAPC(__FUNC_ARGLIST, RANGE8(5));
	int tm[] = { MLIST_REV(5, 4, 3, 2, 1) };
	assert(tm[0] == 1);
	FOLDL(__func1, MLIST_REV(5, 4, 3, 2, 1));
	FOLDR(__func1, MLIST_REV(5, 4, 3, 2, 1));
	int p = FOLDL(__SND, 1, 2, 3, 4, 5);
	assert(p == 5);
	int tl = FOLDL(__func1, 5, 4, 3, 2, 1);
	int tr = FOLDR(__func1, 5, 4, 3, 2, 1);
	assert(tl == (((5 + 4 + 1) + 3 + 1) + 2 +1) + 1 + 1);
	assert(tr == 5 + (4 + (3 + (2 + (1) + 1) + 1) + 1) + 1);
}

void test_bool(){
	assert(1 == NOTB(0));
	assert(0 == NOTB(1));
	assert(0 == NOTB(NOTB(0)));
	assert(0 == NOTB(NOTB(NOTB(1))));
	assert(0 == NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(1))))))))))))));

	assert(0 == ANDB(0, 1));
	assert(0 == ANDB(1, ANDB(0, 1)));
	assert(1 == ANDB(1, NOTB(0)));
	assert(0 == ANDB(1, NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(1)))))))))))))));  

	assert(0 == EQB(ANDB(1, 1), ANDB(1, ANDB(0, 1))));
	assert(1 == EQB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(1))))))))))))), ANDB(1, NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(NOTB(1))))))))))))))));

	assert(-1 == MIF_ELSE(5, -1, 1));
	assert(65535 == MIF_ELSE(NOTB(1), -1, 65535));

	
}

void test_mbyte(){
	byte_t c = INC8(5);
	assert(c == 6);

	byte_t d = DEC8(255);
	assert(d == 254);
	
	byte_t e = DEC8(DEC8(255));
	assert(e == 253);

	byte_t f = INC8(INC8(DEC8(INC8(DEC8(255)))));
	assert(f == 0);

	byte_t k = AZ09_TO_BYTE(A);
	assert(k == 65);
	
	
	k = INC8(INC8(INC8(AZ09_TO_BYTE(a))));
	assert(k == 100);

	k = EQ8(0, 0);
	assert(k == 1);

	k = EQ8(INC8(254), 255);
	assert(k == 1);
	
	k = EQ8(INC8(INC8(254)), 0);
	assert(k == 1);
	
	k = EQ8(INC8(INC8(254)), 255);
	assert(k == 0);
	
}

void test_ctrl(){
	int c[] = { REMOVE_LAST_COMMA(1,2,3,) };
	assert(c[2] == 3);
	int arr[]= {RANGE8(4)};
	assert(arr[3] == 3);
}

#define TEST_CONFIG

#define TEST_VAL   
#define TEST_VAL1  5

#define _macrotest_1 ,
#define config_ternary(macro, true, false) _config_ternary(macro, true, false)
#define _config_ternary(value, true, false) _config_ternary_(_macrotest_##value, true, false)
#define _config_ternary_(comma, true, false) _config_ternary__(comma true, false)
#define _config_ternary__(_, v, ...) v

void test_cfg(){
	/* config check*/
	int a = IS_EMPTY(TEST_CONFIG);
	assert(a == 1);
	int b = IS_EMPTY(TEST_CONFIG1);
	assert(b == 0);

	int c = IS_EMPTY(TEST_CONFIG)?0xBEE:0xFEED;
	assert(c == 0xBEE);

	a = IS_EMPTY(TEST_VAL);
	assert (a == 1);
	/* 这个只能判断是否存在 */
	a = IS_EMPTY(TEST_VAL1);
	assert(a == 0);
	/* 这个能判断是否定义了 */
	a = IS_EXISTS(TEST_VAL1);
	assert(a == 1);

	a = IS_EXISTS(M);
	assert(a == 1);

	/* 未定义或定义为空 -> */
	a =  __CHECK(__PROBE(TEST_BCD));
	assert(a == 1);
	a =  __CHECK(__PROBE(TEST_VAL1));
	assert(a == 1);
	a =  __CHECK(__PROBE(TEST_CONFIG));
	assert(a == 1);

	/* 没定义返回 0*/
	a = config_ternary(TEST_BCD, 1, 0);
	assert(a == 0);
	
	/* 定义了其他值0 */
	a = config_ternary(TEST_VAL1, 1, 0);
	assert(a == 0);

#define OKOKOK	  word_t abc;
	a = config_ternary(OKOKOK, 1, 0);
	assert(a == 0);

	/* 定义了1 返回 1*/
#define TEST_VAL2   1
	a = config_ternary(TEST_VAL2, 1, 0);
	assert(a == 1);
	// a = IS_EXISTS(TESTBCD);
	// assert(a == 0);
}

void test_list(){

	assert(0 == strcmp("list is (a,b,c)\n", "list is "TO_STRING(MLIST(a,b,c))"\n"));
	int UNMLIST((a,b,c)) = 0;
	(void)a; (void) b; (void)c;
	int t = 5;

	char *testc = TO_STRING(MLIST_CONS((a,b,c), d)); // cons(list [a,b,c], d) => list [a,b,c]	
	assert(0 == strcmp("(a,b,c,d)", testc));

	int k = MLIST_HD(MLIST_CONS((t), c)); // => hd(cons(list [t], c)) => t
	assert(k == 5);

	char *testd = TO_STRING(MLIST_APPEND((t,a,c), (b,d)));
	assert(0 == strcmp("(t,a,c,b,d)", testd));

	char *teste = TO_STRING(MLIST_REST(MLIST_APPEND((t,a,b), (c,d))));
	assert(0 == strcmp("(a,b,c,d)", teste));

}



int main(){
	
	test_str();
	test_argc();
	
	test_eval();

	test_bool();

	test_mbyte();
	
	test_ctrl();
	test_cfg();
	test_list();
	int a = 5;
	int b = 5;
	assert((a>=b) == 1);
	// test_meff();
	printf("all test passed\n");
	return 0;
}
